import os

from module.static_module.parent.model import DynamicModule
from module.dynamic_module.machine_learning.engine import MLEngine
from core.constant import *

from tools.framework import get_date_str, get_ui_value, load_module_from_path

import pandas as pd


class MachineLearningModel(DynamicModule):
    def __init__(self, master):
        super().__init__(master, Module.MachineLearning)
        # 实体类映射视图类变量数据
        self.data_name_ls = []
        self.symbol_name_ls = []
        self.target_name_ls = []
        self.engine_class_ls = []
        self.result_folder_ls = []
        # 映射视图类变量数据到实体类
        self.data_name = None
        self.symbol_name = None
        self.target_name = None
        self.engine_class = None
        self.result_folder = None
        # 必要结构变量
        self.ml_engine = None

    def sec_init(self):
        from tools.framework import gen_result_folder_name  # 避免循环调用

        self.data_name_ls = self.master.file_manager.data_def_group_dc[DataDefGroup.Mk.value] + \
                            self.master.file_manager.data_def_group_dc[DataDefGroup.MkFt.value] + \
                            self.master.file_manager.data_def_group_dc[DataDefGroup.MkFtSg.value]
        self.symbol_name_ls = []
        self.target_name_ls = []
        self.engine_class_ls = self.master.file_manager.data_def_group_dc[DataDefGroup.DDQMLEName.value]
        self.result_folder_ls = [gen_result_folder_name(ResultFolder.MLE)]
        pass

    def get_ui_params(self):
        # 获取ui界面的相关参数
        values, indices = self.master.main_window_view.dynamic_module_view.auto_layout.get_value(
            LabelMember.DataName)
        self.data_name = get_ui_value(values, indices, WidgetCategory.Combobox)
        values, indices = self.master.main_window_view.dynamic_module_view.auto_layout.get_value(
            LabelMember.SymbolName)
        self.symbol_name = get_ui_value(values, indices, WidgetCategory.Combobox)
        values, indices = self.master.main_window_view.dynamic_module_view.auto_layout.get_value(
            LabelMember.TargetName)
        self.target_name = get_ui_value(values, indices, WidgetCategory.Combobox)
        values, indices = self.master.main_window_view.dynamic_module_view.auto_layout.get_value(
            LabelMember.EngineClass)
        self.engine_class = get_ui_value(values, indices, WidgetCategory.Combobox)
        values, indices = self.master.main_window_view.dynamic_module_view.auto_layout.get_value(
            LabelMember.ResultFolder)
        self.result_folder = get_ui_value(values, indices, WidgetCategory.Entry)

    def on_data_name_change(self):
        values, indices = self.master.main_window_view.dynamic_module_view.auto_layout.get_value(
            LabelMember.DataName)
        self.data_name = get_ui_value(values, indices, WidgetCategory.Combobox)
        self.symbol_name_ls = self.master.file_manager.describe_all_dc[self.data_name].symbol_ls
        self.target_name_ls = self.master.file_manager.describe_all_dc[self.data_name].merge_columns_ls[1:]

    def on_run_thread(self):
        try:
            # 点击运行按钮回调
            self.get_ui_params()
            # 预检查
            if len(self.target_name) != 1:
                raise ValueError("标签数据应仅为一列，选择的标签数量不为1。")
            # 加载数据
            data_describe = self.master.file_manager.describe_all_dc[self.data_name]
            data_path = data_describe.path
            data_df_dc: dict[str, pd.DataFrame] = self.master.file_manager.read_dc_csv(data_path)
            ori_data_df = data_df_dc[self.symbol_name]
            # 加载机器学习引擎
            engine_path = os.path.join(self.master.file_manager.strategy_path, self.engine_class)
            engine_py = load_module_from_path(engine_path)
            ml_engine_c = engine_py.DDQMLEngine
            self.ml_engine: MLEngine = ml_engine_c(self.master.file_manager)
            # 生成引擎基础属性数据
            # 获取所有字段
            all_col_ls = data_describe.merge_columns_ls[1:]
            target_col = self.target_name[0]
            # 除去目标字段
            feature_col_ls = []
            for col in all_col_ls[1:]:
                if col != target_col:
                    feature_col_ls.append(col)

            self.ml_engine.ori_data(ori_data_df, feature_col_ls, target_col)
            self.ml_engine.scale_data(scale_plan="mean_std")
            # 执行训练方法
            self.ml_engine.train_model()
            # 保存模型到本地
            self.ml_engine.save_model()

        except Exception as e:
            import traceback
            info = f"[{self.module.value}]任务运行出错，错误信息{e}"
            self.master.file_manager.log_engine.emit(info, LogName.Running)
            traceback.print_exc()
            pass
        self.task_end()



